#ifndef TPS929120_TPS929120_H_
#define TPS929120_TPS929120_H_

#include "user_define.h"
#include "Cpu.h"
#include "bsp_uart_driver.h"


/*************************************************************************************************************************
*[User Configuration Data]
 *************************************************************************************************************************/
#define DRIVER_CHIP_NUM     16
#define UART_COM_NUM        2

#define CHANNEL_CURRENT_MAX          17  /* mA */
#define TIMEOUT_CNT_MAX              ((uint32_t) 0x6FF)

#define TPS_TX_BUF_SIZE    16
#define TPS_RX_BUF_SIZE    16
#define TPS_BC_BUF_SIZE    16

#define INVALID_DEV_INSTANCE      (0xFF)


/*************************************************************************************************************************
*[Driver Feature]
 *************************************************************************************************************************/
#define DRIVER_CHANNEL_NUM        12U
#define TPS_CHANNEL_0             0
#define TPS_CHANNEL_1             1
#define TPS_CHANNEL_2             2
#define TPS_CHANNEL_3             3
#define TPS_CHANNEL_4             4
#define TPS_CHANNEL_5             5
#define TPS_CHANNEL_6             6
#define TPS_CHANNEL_7             7
#define TPS_CHANNEL_8             8
#define TPS_CHANNEL_9             9
#define TPS_CHANNEL_10            10
#define TPS_CHANNEL_11            11

#define TPS_PWM_DUTY_MAX          ((uint16_t) 0xFFF)



/*************************************************************************************************************************
*[Protocol Data]
 *************************************************************************************************************************/
#define FRMAE_SYNC_BYTE           ((uint8_t)0x55)
#define DATA_LEN_BIT_MASK         ((uint8_t)0x30)
#define DATA_LEN_BIT_SHIFT        ((uint8_t)0x04)
#define DATA_LEN_1_BYTES          ((uint8_t)0x00)
#define DATA_LEN_2_BYTES          ((uint8_t)0x01)
#define DATA_LEN_4_BYTES          ((uint8_t)0x02)
#define DATA_LEN_8_BYTES          ((uint8_t)0x03)
#define DATA_LEN_BIT(byte, x)     (byte = (byte & (~DATA_LEN_BIT_MASK)) | ((x & 0x03) << DATA_LEN_BIT_SHIFT))
#define WR_RD_BIT_MASK            ((uint8_t)0x80)
#define WR_RD_BIT_SHIFT           ((uint8_t)0x07)
#define WR_RD_WRITE               ((uint8_t)0x01)
#define WR_RD_READ                ((uint8_t)0x00)
#define WR_RD_BIT(byte, x)        (byte = (byte & (~WR_RD_BIT_MASK)) | ((x & 0x01) << WR_RD_BIT_SHIFT))
#define COMM_MODE_BIT_MASK        ((uint8_t)0x40)
#define COMM_MODE_BIT_SHIFT       ((uint8_t)0x06)
#define COMM_MODE_BROADCAST       ((uint8_t)0x01)
#define COMM_MODE_SINGLE_DEV      ((uint8_t)0x00)
#define COMM_MODE_BIT(byte, x)    (byte = (byte & (~COMM_MODE_BIT_MASK)) | ((x & 0x01) << COMM_MODE_BIT_SHIFT))

#define CRC_POLY_VALUE            (0x31U)
#define CRC_INIT_VALUE            (0xFFU)
/*************************************************************************************************************************/


/*************************************************************************************************************************
*[Register Address]
 *************************************************************************************************************************/
#define REG_ADD_IOUT0             ((uint8_t)0x00)
#define REG_ADD_IOUTx(X)          ((uint8_t)REG_ADD_IOUT0 + X)
#define REG_ADD_PWM0              ((uint8_t)0x20)
#define REG_ADD_PWMx(X)           ((uint8_t)REG_ADD_PWM0 + X)
#define REG_ADD_PWML0             ((uint8_t)0x40)
#define REG_ADD_PWMLx(X)          ((uint8_t)REG_ADD_PWML0 + X)
#define REG_ADD_CFG_EN0           ((uint8_t)0x50)
#define REG_ADD_CFG_EN1           ((uint8_t)0x51)
#define REG_ADD_CFG_DIAGEN0       ((uint8_t)0x54)
#define REG_ADD_CFG_DIAGEN1       ((uint8_t)0x55)
#define REG_ADD_CFG_MISC0         ((uint8_t)0x56)
#define REG_ADD_CFG_MISC1         ((uint8_t)0x57)
#define REG_ADD_CFG_MISC2         ((uint8_t)0x58)
#define REG_ADD_CFG_MISC3         ((uint8_t)0x59)
#define REG_ADD_CFG_MISC4         ((uint8_t)0x5A)
#define REG_ADD_CFG_MISC5         ((uint8_t)0x5B)
#define REG_ADD_CLR               ((uint8_t)0x60)
#define REG_ADD_CFG_LOCK          ((uint8_t)0x61)
#define REG_ADD_CFG_MISC6         ((uint8_t)0x62)
#define REG_ADD_CFG_MISC7         ((uint8_t)0x63)
#define REG_ADD_CFG_MISC8         ((uint8_t)0x64)
#define REG_ADD_CFG_MISC9         ((uint8_t)0x65)
#define REG_ADD_FLAG0             ((uint8_t)0x70)
#define REG_ADD_FLAG1             ((uint8_t)0x71)
#define REG_ADD_FLAG2             ((uint8_t)0x72)
#define REG_ADD_FLAG3             ((uint8_t)0x73)
#define REG_ADD_FLAG4             ((uint8_t)0x74)
#define REG_ADD_FLAG5             ((uint8_t)0x75)
#define REG_ADD_FLAG6             ((uint8_t)0x76)
#define REG_ADD_FLAG7             ((uint8_t)0x77)
#define REG_ADD_FLAG8             ((uint8_t)0x78)
#define REG_ADD_FLAG11            ((uint8_t)0x7B)
#define REG_ADD_FLAG12            ((uint8_t)0x7C)
#define REG_ADD_FLAG13            ((uint8_t)0x7D)
#define REG_ADD_FLAG14            ((uint8_t)0x7E)
/*************************************************************************************************************************/


/*************************************************************************************************************************
*[Register Parameter Macro]
 *************************************************************************************************************************/
#define PWM_FREQ_200HZ            ((uint8_t)0x0)
#define PWM_FREQ_250HZ            ((uint8_t)0x1)
#define PWM_FREQ_300HZ            ((uint8_t)0x2)
#define PWM_FREQ_350HZ            ((uint8_t)0x3)
#define PWM_FREQ_400HZ            ((uint8_t)0x4)
#define PWM_FREQ_500HZ            ((uint8_t)0x5)
#define PWM_FREQ_600HZ            ((uint8_t)0x6)
#define PWM_FREQ_800HZ            ((uint8_t)0x7)
#define PWM_FREQ_1000HZ           ((uint8_t)0x8)
#define PWM_FREQ_1200HZ           ((uint8_t)0x9)
#define PWM_FREQ_2000HZ           ((uint8_t)0xA)
#define PWM_FREQ_4000HZ           ((uint8_t)0xB)
#define PWM_FREQ_5900HZ           ((uint8_t)0xC)
#define PWM_FREQ_7800HZ           ((uint8_t)0xD)
#define PWM_FREQ_9600HZ           ((uint8_t)0xE)
#define PWM_FREQ_20800HZ          ((uint8_t)0xF)

#define REFRANG_512               ((uint8_t)0x03)
#define REFRANG_256               ((uint8_t)0x02)
#define REFRANG_128               ((uint8_t)0x01)
#define REFRANG_64                ((uint8_t)0x00)


#define LOCK_PWM(x)               ((uint8_t)x<<0)
#define LOCK_IOUT(x)              ((uint8_t)x<<1)
#define LOCK_CONF(x)              ((uint8_t)x<<2)
#define LOCK_CLR(x)               ((uint8_t)x<<3)


#define MSIC7_SHAREPWM_MASK       ((uint8_t)0x10)
#define MSIC7_SHAREPWM_SHIFT      ((uint8_t)4)
/*************************************************************************************************************************/


typedef enum
{
	eBurst_1_Byte = 0,
	eBurst_2_Byte = 1,
	eBurst_4_Byte = 2,
	eBurst_8_Byte = 3,
}BurstMode_e;

typedef enum
{
	eComMode_SD = 0,  /* single device */
	eComMode_BC = 1,  /* broadcast */
}TpsComMode_e;

typedef enum
{
	eEvent_SendOneData,
	eEvent_RecvOneData,
	eEvent_SendComplete,
	eEvent_RecvComplete,
	eEvent_Error,
	eEvent_Idle,
}ComEvent_e;


typedef enum
{
	eIDLE,
	eBusy,
	eTimout,
	eError,
}TpsComState_e;


typedef status_t (*UartCom_SendData)(uint8_t* pu8Buf, uint8_t u8Datalen);
typedef status_t (*UartCom_ReceiveData)(uint8_t* pu8Buf, uint8_t u8Datalen);
typedef void (*UartCom_EventCallback)(uint8_t u8ComInst, ComEvent_e eEvent);
typedef struct
{
	uint8_t       u8DevInst;
	TpsComState_e eUartComState;
	uint8_t       u8CanPHYFlag;
	uint8_t       u8ComDataBuf[TPS_BC_BUF_SIZE];
	UartCom_SendData pfSendData;
	UartCom_ReceiveData pfReceiveData;
}TpsCom_t;

typedef struct
{
	uint8_t       u8CanPHYFlag;
	UartCom_SendData pfSendData;
	UartCom_ReceiveData pfReceiveData;
}TpsCom_UserCfg_t;


#define TPS_MODE_INIT        0
#define TPS_MODE_NORMAL      1
#define TPS_MODE_FAILSAFE    2

typedef struct
{
	uint8_t u8DevAddr;
	uint8_t u8DevMode;
	uint8_t u8TxDataLen;
	uint8_t u8TxBuf[TPS_TX_BUF_SIZE];
	uint8_t u8RxBuf[TPS_RX_BUF_SIZE];
	uint8_t u8RxDataLen;
	TpsComState_e eDevComState;
	uint8_t u8UartComInst;
	uint16_t u16ChannelEnbits;
	uint16_t u16ChnlUseMask;
}TpsDriver_t;


typedef struct
{
	uint8_t u8DevAddr;
	uint8_t u8UartComInst;
	uint16_t u16ChnlUseMask;
}TpsDriver_UserCfg_t;

/*************************************************************************************************************************
*[External Variant]
 *************************************************************************************************************************/
extern TpsDriver_t  g_stTpsDrivers[DRIVER_CHIP_NUM];

/*************************************************************************************************************************
*[External Interface Function]
 *************************************************************************************************************************/
extern uint8_t Tps_CrcCalc(uint8_t* pucData, uint16_t usDataLen);

extern void Tps_ComEventCallBack(uint8_t u8ComInst, ComEvent_e eEvent);

extern status_t Tps_WriteOneRegBlock(uint8_t u8DevInst, uint8_t u8RegAdd, uint8_t u8Data, uint8_t u8RecvEn);

extern status_t Tps_WriteRegsBlocking(uint8_t u8DevInst, uint8_t u8RegAdd, uint8_t* pu8DataBuf, BurstMode_e eBurstmode, uint8_t u8RecvEn);

extern status_t Tps_ReadOneRegBlocking(uint8_t u8DevInst, uint8_t u8RegAdd, uint8_t* u8Data);

extern status_t Tps_SetPwmReqAndRefRang(uint8_t u8DevInst, uint8_t u8Freq, uint8_t u8RefRang);

extern status_t Tps_BC_SetPwmReqAndRefRang(uint8_t u8ComMask, uint8_t u8Freq, uint8_t u8RefRang);

extern status_t Tps_SetChannelPWMDuty(uint8_t u8DevInst, uint8_t u8ChnlNum, uint16_t u16PwmDuty);

extern status_t Tps_SetChannelPWMDutyEn(uint8_t u8DevInst, uint8_t u8ChnlNum, uint16_t u16PwmDuty);

extern status_t Tps_SetLock(uint8_t u8DevInst, uint8_t u8LockBits);

extern status_t Tps_BC_SetLock(uint8_t u8ComMask, uint8_t u8LockBits);

extern status_t Tps_SetChannelEn(uint8_t u8DevInst, uint16_t u16Enbits);

extern status_t Tps_DisableAllChannel(uint8_t u8DevInst);

extern status_t Tps_EnableAllChannel(uint8_t u8DevInst);

extern status_t Tps_BC_SetChannelPWMDuty(uint8_t u8ComMask, uint8_t u8ChnlNum, uint16_t u16PwmDuty);

extern status_t Tps_BC_SetChannelEn(uint8_t u8ComMask, uint16_t u16Enbits);

extern status_t Tps_SetMISC0(uint8_t u8DevInst, uint8_t u8RegData);

extern status_t Tps_BC_SetMISC0(uint8_t u8ComMask, uint8_t u8RegData);

extern status_t Tps_SetMISC2(uint8_t u8DevInst, uint8_t u8RegData);

extern status_t Tps_BC_SetMISC2(uint8_t u8ComMask, uint8_t u8RegData);

extern status_t Tps_SetMISC4(uint8_t u8DevInst, uint8_t u8RegData);

extern status_t Tps_BC_SetMISC4(uint8_t u8ComMask, uint8_t u8RegData);

extern status_t Tps_SetMISC7(uint8_t u8DevInst, uint8_t u8RegData);

extern status_t Tps_SetMISC8(uint8_t u8DevInst, uint8_t u8RegData);

extern status_t Tps_BC_SetMISC7(uint8_t u8ComMask, uint8_t u8RegData);

extern status_t Tps_BC_SetMISC8(uint8_t u8ComMask, uint8_t u8RegData);

extern status_t Tps_SetCLR(uint8_t u8DevInst, uint8_t u8RegData);

extern status_t Tps_BC_SetCLR(uint8_t u8ComMask, uint8_t u8RegData);

extern status_t Tps_BC_DisableAllChannel(void);

extern status_t Tps_BC_EnableAllChannel(void);

extern status_t Tps_SetIOut(uint8_t u8DevInst, uint8_t u8ChnlNum, uint8_t u8Curr);

extern status_t Tps_SetAllIOut(uint8_t u8DevInst, uint8_t u8Curr);

extern status_t Tps_BC_SetIOut(uint8_t u8ComMask, uint8_t u8ChnlNum, uint8_t u8Curr);

extern status_t Tps_CfgInit(const TpsCom_UserCfg_t* pstComCfg, uint8_t u8ComCfgNum,
		                    const TpsDriver_UserCfg_t* pstTpsCfg, uint8_t DrvCfgNum);
extern void Tps_Init(void);
#endif /* TPS929120_TPS929120_H_ */
